//
// Created by HP on 2025/11/5.
//

#include <random>
#include <cassert>
#include "../include/util.h"

std::string getFormattedDate() {
    // 1. 获取当前系统时间（时间戳，从1970年1月1日至今的秒数）
    std::time_t now = std::time(nullptr);

    // 2. 转换为本地时间（结构体包含年、月、日等信息）
    std::tm* localTime = std::localtime(&now);
    if (localTime == nullptr) {
        return ""; // 转换失败返回空
    }

    // 3. 格式化：年+1900（因为tm_year是从1900开始的偏移量），月+1（tm_mon从0开始）
    char buffer[11]; // "YYYY/MM/DD" 共10个字符+1个结束符
    std::strftime(buffer, sizeof(buffer), "%Y-%m-%d", localTime);

    return std::string(buffer);
}

// 新增：获取当前时间（几时几分几秒，格式 HH:MM:SS）
std::string getFormattedTime() {
    // 1. 获取当前系统时间戳
    std::time_t now = std::time(nullptr);

    // 2. 转换为本地时间（结构体包含时、分、秒信息）
    std::tm* localTime = std::localtime(&now);
    if (localTime == nullptr) {
        return ""; // 转换失败返回空字符串
    }

    // 3. 格式化：HH:MM:SS（24小时制，不足两位补零）
    char buffer[9]; // "HH:MM:SS" 共8个字符 + 1个结束符
    // strftime 格式说明：%H=24小时制（00-23），%M=分钟（00-59），%S=秒（00-59）
    std::strftime(buffer, sizeof(buffer), "%H:%M:%S", localTime);

    return std::string(buffer);
}

std::string getFormattedDateTime() {
    std::time_t now = std::time(nullptr);
    std::tm* localTime = std::localtime(&now);
    if (localTime == nullptr) {
        return "";
    }
    char buffer[20]; // "YYYY/MM/DD HH:MM:SS" 共19字符 + 结束符
    std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", localTime);
    return std::string(buffer);
}

std::string addHour(const std::string& time, int hours) {
    // 1. 解析输入时间字符串到 tm 结构体
    std::tm tm_time = {};
    // 格式匹配：%Y=年，%m=月，%d=日，%H=24小时制，%M=分，%S=秒
    if (sscanf(time.c_str(), "%d-%d-%d %d:%d:%d",
               &tm_time.tm_year, &tm_time.tm_mon, &tm_time.tm_mday,
               &tm_time.tm_hour, &tm_time.tm_min, &tm_time.tm_sec) != 6) {
        return ""; // 格式错误，返回空字符串
    }

    // 2. 修正 tm 结构体的偏移量（tm_year 是1900年至今的偏移，tm_mon 是0-11）
    tm_time.tm_year -= 1900; // 输入的是完整年份（如2024），需转为偏移量
    tm_time.tm_mon -= 1;     // 输入的是1-12月，需转为0-11

    // 3. 转换为时间戳，添加指定小时数
    std::time_t time_stamp = std::mktime(&tm_time);
    if (time_stamp == -1) {
        return ""; // 转换失败（如无效日期），返回空
    }
    time_stamp += hours * 3600; // 1小时=3600秒，直接累加时间戳

    // 4. 转换回本地时间并格式化
    std::tm* new_tm = std::localtime(&time_stamp);
    if (new_tm == nullptr) {
        return "";
    }
    char buffer[20];
    std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", new_tm);

    return std::string(buffer);
}

std::string addMonth(const std::string& time, int months) {
    // 1. 解析输入时间到 tm 结构体
    std::tm tm_time = {};
    if (sscanf(time.c_str(), "%d-%d-%d %d:%d:%d",
               &tm_time.tm_year, &tm_time.tm_mon, &tm_time.tm_mday,
               &tm_time.tm_hour, &tm_time.tm_min, &tm_time.tm_sec) != 6) {
        return ""; // 格式错误返回空
    }

    // 2. 修正偏移量（转为 tm 结构体的内部格式）
    tm_time.tm_year -= 1900; // 年份：2024 → 124（1900至今偏移）
    tm_time.tm_mon -= 1;     // 月份：1-12 → 0-11

    // 3. 计算目标月份（处理跨年）
    int target_year = tm_time.tm_year;
    int target_mon = tm_time.tm_mon + months;

    // 调整年份和月份（如：13月→次年1月，-1月→去年11月）
    if (target_mon >= 12) {
        target_year += target_mon / 12;
        target_mon = target_mon % 12;
    } else if (target_mon < 0) {
        int year_offset = (target_mon - 11) / 12; // 负数向上取整（如-1→-1年，-13→-2年）
        target_year += year_offset;
        target_mon = target_mon - year_offset * 12;
    }

    // 4. 处理「当月天数不足」的边界场景（如：3月31日+1月→4月30日，2月29日+1年→3月1日）
    tm_time.tm_year = target_year;
    tm_time.tm_mon = target_mon;
    // 先将日期设为当月最后一天，再取最小值（避免日期溢出）
    tm_time.tm_mday = 31; // 临时设为31天（后续 mktime 会自动修正为当月实际最大天数）
    std::time_t temp_stamp = std::mktime(&tm_time);
    if (temp_stamp == -1) return "";
    std::tm* temp_tm = std::localtime(&temp_stamp);
    if (temp_tm == nullptr) return "";
    // 恢复原日期（若原日期超过当月最大天数，则取当月最后一天）
    tm_time.tm_mday = std::min(tm_time.tm_mday, temp_tm->tm_mday);

    // 5. 转换为时间戳并格式化输出
    std::time_t final_stamp = std::mktime(&tm_time);
    if (final_stamp == -1) return "";
    std::tm* new_tm = std::localtime(&final_stamp);
    if (new_tm == nullptr) return "";

    char buffer[20];
    std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", new_tm);
    return std::string(buffer);
}


std::string addYear(const std::string& time, int years) {
    // 1. 解析输入时间到 tm 结构体
    std::tm tm_time = {};
    if (sscanf(time.c_str(), "%d-%d-%d %d:%d:%d",
               &tm_time.tm_year, &tm_time.tm_mon, &tm_time.tm_mday,
               &tm_time.tm_hour, &tm_time.tm_min, &tm_time.tm_sec) != 6) {
        return ""; // 格式错误返回空
    }

    // 2. 修正偏移量并添加年份
    tm_time.tm_year -= 1900; // 2024 → 124
    tm_time.tm_mon -= 1;     // 1-12 → 0-11
    tm_time.tm_year += years; // 直接添加年份（跨年自动处理）

    // 3. 处理闰年2月29日的边界场景（如：2024-02-29 +1年→2025-03-01）
    std::time_t temp_stamp = std::mktime(&tm_time);
    if (temp_stamp == -1) {
        // 若转换失败（如非闰年的2月29日），调整为3月1日
        tm_time.tm_mon = 2; // 3月（0-11）
        tm_time.tm_mday = 1;
        temp_stamp = std::mktime(&tm_time);
        if (temp_stamp == -1) return "";
    }

    // 4. 格式化输出
    std::tm* new_tm = std::localtime(&temp_stamp);
    if (new_tm == nullptr) return "";

    char buffer[20];
    std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", new_tm);
    return std::string(buffer);
}

/**
 * 重置时间字符串的小时部分，并保持分钟和秒为00
 * @param time 输入的时间字符串，格式为"YYYY-MM-DD HH:MM:SS"
 * @return 返回修改后的时间字符串，小时部分保持不变，分钟和秒被设置为00
 */
std::string reSetHour(const std::string& time) {
    // 使用substr函数提取从开始到第13个字符（包含空格）的子串，即"YYYY-MM-DD HH"
    // 然后拼接":00:00"将分钟和秒设置为00
    return time.substr(0, 13) + ":00:00";
}

/**
 * @brief 重置日期时间为当月第一天
 * 
 * 该函数接收一个日期时间字符串，将其重置为当月的第一天，并将时间部分设置为00:00:00
 * 
 * @param time 输入的日期时间字符串，格式为"YYYY-MM-DD HH:MM:SS"
 * @return std::string 返回重置后的日期时间字符串，格式为"YYYY-MM-DD HH:MM:SS"，其中日期为当月第一天
 */
std::string reSetMonth(const std::string& time) {
    // 使用substr提取原日期字符串的前8位（年-月-日部分）
    // 然后添加"-01 00:00:00"将日期设置为当月第一天，时间设置为午夜
    return time.substr(0, 8) + "-01 00:00:00";
}

/**
 * 重置日期字符串为当年的第一天
 * @param time 输入的日期时间字符串，格式为"YYYY-MM-DD HH:MM:SS"
 * @return 返回重置后的日期时间字符串，年份与输入相同，其他部分被重置为"01-01 00:00:00"
 */
std::string reSetYear(const std::string& time) {
    // 使用substr提取年份部分（前5个字符）
    // 然后拼接"-01-01 00:00:00"形成新的日期字符串
    return time.substr(0, 5) + "-01-01 00:00:00";
}

/**
 * 重置日期时间为当天的起始时间（00:00:00）
 * @param time 输入的日期时间字符串，格式应为"YYYY-MM-DD HH:MM:SS"
 * @return 返回重置后的日期时间字符串，重置为"YYYY-MM-DD 00:00:00"格式
 */
std::string reSetDay(const std::string& time) {  // 接收一个字符串引用参数，返回处理后的字符串
    return time.substr(0, 10) + " 00:00:00";  // 提取日期部分（前10个字符），并拼接上" 00:00:00"
}

std::string generateVerificationCode() {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(100000, 999999);
    return std::to_string(dis(gen));
}

/**
 * 分割字符串函数
 * @param str 要分割的字符串
 * @param delimiter 分隔符
 * @return 分割后的字符串向量
 */
std::vector<std::string> split(const std::string& str, char delimiter){
    std::vector<std::string> tokens;  // 存储分割后的字符串
    std::string token;                // 临时存储每个分割出的字符串
    std::istringstream tokenStream(str);  // 创建字符串输入流
    // 使用getline函数按分隔符分割字符串
    while (std::getline(tokenStream, token, delimiter)) {
        tokens.push_back(token);  // 将分割出的字符串添加到向量中
    }
    return tokens;  // 返回分割结果
}

/**
 * 将map转换为JSON格式的字符串
 * @param mp 输入的map，键值类型均为string
 * @return 返回JSON格式的字符串
 */
std::string mpToJson(const std::map<std::string, std::string>& mp) {
    std::string json = "{";  // 初始化JSON字符串，开始标记
    // 遍历map中的每个键值对
    for (const auto& pair : mp) {
        // 将键值对添加到JSON字符串中，格式为"key":"value",
        json += "\"" + pair.first + "\":\"" + pair.second + "\",";
    }
    // 如果JSON字符串不为空（即map不为空），移除最后一个多余的逗号
    if (!json.empty()) {
        json.pop_back(); // 移除最后一个逗号
    }
    json += "}";  // 添加JSON字符串的结束标记
    return json;  // 返回生成的JSON字符串
}

// 辅助函数：获取指定年月的天数（处理闰年）
int getDaysInMonth(int year, int month) {
    if (month == 2) {
        // 闰年判断：能被400整除，或能被4整除但不能被100整除
        if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) {
            return 29;
        } else {
            return 28;
        }
    } else if (month == 4 || month == 6 || month == 9 || month == 11) {
        return 30;
    } else {
        return 31;
    }
}

// 解析日期字符串为年、月、日（假设格式为 "yyyy-mm-dd"）
bool parseDate(const std::string& date, int& year, int& month, int& day) {
    if (date.size() < 10) return false;
    try {
        year = std::stoi(date.substr(0, 4));
        month = std::stoi(date.substr(5, 2));
        day = std::stoi(date.substr(8, 2));
        // 简单校验日期合法性
        if (month < 1 || month > 12 || day < 1 || day > getDaysInMonth(year, month)) {
            return false;
        }
        return true;
    } catch (...) {
        return false; // 解析失败（非数字字符等）
    }
}

// 将年、月、日格式化为 "yyyy-mm-dd" 字符串（确保两位数）
std::string formatDate(int year, int month, int day) {
    std::stringstream ss;
    ss << std::setw(4) << std::setfill('0') << year << "-"
       << std::setw(2) << std::setfill('0') << month << "-"
       << std::setw(2) << std::setfill('0') << day;
    return ss.str();
}

// 给日期加减天数（支持跨月、跨年，days范围：-60~60）
std::string addDay(const std::string& date, int days) {
    assert(days >= -60 && days <= 60); // 调整天数范围限制

    int year, month, day;
    if (!parseDate(date.substr(0, 10), year, month, day)) {
        return ""; // 日期格式错误，返回空
    }

    day += days; // 累加天数（可能为负数）

    // 处理跨月/跨年（循环调整，直到天数在当月范围内）
    while (true) {
        int max_day = getDaysInMonth(year, month);
        if (day >= 1 && day <= max_day) {
            break; // 天数在当月范围内，无需调整
        }

        if (day > max_day) {
            // 天数超过当月，向前进位到下个月
            day -= max_day;
            month++;
            if (month > 12) {
                month = 1;
                year++;
            }
        } else {
            // 天数为负数，向后退位到上个月
            month--;
            if (month < 1) {
                month = 12;
                year--;
            }
            day += getDaysInMonth(year, month); // 加上上个月的总天数
        }
    }

    return formatDate(year, month, day);
}
std::string vecToStr(const std::vector<std::string>& vec) {
    std::string str="[";
    for (const auto& item : vec) {
        str +=  item + ",";
    }
    if (!str.empty()) {
        str.pop_back(); // 移除最后一个逗号
    }
    str += "]";
    return str;
}

std::string vecToStr(const std::vector<std::map<std::string,std::string>>& vec) {
    std::vector<std::string> tmp;
    for (auto& item : vec) {
        tmp.push_back(mpToJson(item));
    }
    return vecToStr(tmp);
}

std::string getToday() {
    time_t now = time(nullptr);
    if (now == -1) {
        return ""; // 获取时间戳失败
    }

    struct tm localTime{}; // 栈上的结构体，线程私有
    // 线程安全版本：将结果写入localTime，而非内部静态缓冲区
    if (localtime_s(&localTime, &now) != 0) {
        return ""; // 转换失败
    }

    char buffer[11];
    // 格式化日期（确保格式与缓冲区大小匹配）
    if (std::strftime(buffer, sizeof(buffer), "%Y-%m-%d", &localTime) == 0) {
        return ""; // 格式化失败（理论上不会发生）
    }

    return buffer;
}

std::string TypeToTicketsType(const std::string& Type) {
    std::vector<std::string> s = split(Type, ' ');
    if (s.size()!=2) return "";
    if (s[0]=="Train") {
        if (s[1]=="高铁一等座") {
            return "HighFirstClass";
        } else if(s[1]=="高铁二等座") {
            return "HighSecondClass";
        } else if(s[1]=="动车一等座") {
            return "QuickFirstClass";
        } else if(s[1]=="动车二等座") {
            return "QuickSecondClass";
        } else if(s[1]=="软卧") {
            return "SoftBed";
        } else if(s[1]=="硬卧") {
            return "HardBed";
        } else if(s[1]=="硬座") {
            return "HardSeat";
        } else if(s[1]=="软座") {
            return "SoftSeat";
        } else if(s[1]=="无座") {
            return "NoSeat";
        } else {
            return "";
        }
    } else if(s[0]=="Car") {
        return "CarSeat";
    } else if(s[0]=="Plane") {
        if (s[1]=="头等舱") {
            return "FlyFirstClass";
        } else if (s[1]=="经济舱") {
            return "FlyEconomyClass";
        } else {
            return "";
        }
    } else {
        return "";
    }
}

std::string TicketsTypeToType(const std::string& Type) {
    if (Type=="HighFirstClass") {
        return "高铁一等座";
    } else if(Type=="HighSecondClass") {
        return "高铁二等座";
    } else if(Type=="QuickFirstClass") {
        return "动车一等座";
    } else if(Type=="QuickSecondClass") {
        return "动车二等座";
    } else if(Type=="SoftBed") {
        return "软卧";
    } else if(Type=="HardBed") {
        return "硬卧";
    } else if(Type=="SoftSeat") {
        return "软座";
    } else if(Type=="HardSeat") {
        return "硬座";
    } else if(Type=="NoSeat") {
        return "无座";
    } else if(Type=="CarSeat") {
        return "汽车座位";
    } else if(Type=="FlyFirstClass") {
        return "头等舱";
    } else if(Type=="FlyEconomyClass") {
        return "经济舱";
    } else {
        return "";
    }
}

std::vector<std::string> strTovec(const std::string & vec) {
    bool cnt = false;
    int u=1;
    std::vector<std::string> res;
    for(int i=1;i+1<vec.size();i++) {
        if(vec[i]=='\"') {
            if(cnt) {
                res.push_back(vec.substr(u+1, i-u-1));
            } else {
                u=i;
            }
            cnt=!cnt;
        }
    }
    return res;
}

bool VaildTicket(std::string& ticket) {
    return ticket=="HighFirstClass" || ticket=="HighSecondClass" || ticket=="QuickFirstClass" || ticket=="QuickSecondClass" || ticket=="SoftBed" || ticket=="HardBed" || ticket=="SoftSeat" || ticket=="HardSeat" || ticket=="NoSeat" || ticket=="CarSeat" || ticket=="FlyFirstClass" || ticket=="FlyEconomyClass";
}

std::string ticketTypeToStr(const std::string& type) {
    if (type=="HighFirstClass"||type=="HighSecondClass") {
        return "高铁";
    }
    if (type=="QuickFirstClass"||type=="QuickSecondClass") {
        return "动车";
    }
    if (type=="SoftBed"||type=="HardBed"||type=="SoftSeat"||type=="HardSeat"||type=="NoSeat") {
        return "火车";
    }
    if (type=="CarSeat") {
        return "汽车";
    }
    if (type=="FlyFirstClass"||type=="FlyEconomyClass") {
        return "飞机";
    }
    return "";
}
// JsonValue 实现已移至独立的 JsonValue.cpp 文件